package org.swxjava.assembler.avm1;

import org.swxjava.util.Log;
import org.swxjava.util.LogFactory;
import org.swxjava.util.StringUtils;

import org.swxjava.assembler.Constants;
import org.swxjava.assembler.Debugger;
import org.swxjava.assembler.ObjectCompiler;

public class SwxResult implements ObjectCompiler {

	/** Logger */
	private static final Log LOG = LogFactory.getLog(SwxResult.class);
	
	/** var result */
	public static final String VAR_RESULT = "726573756C74";
	
	/** value */
	private ObjectCompiler value = null;
	
	/** debug mode */
	private boolean debug = false;

	/** allow domain */
	private boolean allowDomain = false;
	
	/** url */
	private String url = null;
	
	public SwxResult(ObjectCompiler value) {
		this.value = value;
	}

	public int getByteSize() {
		return toString().length() / 2;
	}

	public byte[] toBytecode() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean isDebug() {
		return debug;
	}

	public void setDebug(boolean debug) {
		this.debug = debug;
	}

	public boolean isAllowDomain() {
		return allowDomain;
	}

	public void setAllowDomain(boolean allowDomain) {
		this.allowDomain = allowDomain;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public boolean isComplex() {
		boolean complex = false;
		complex = (value instanceof AsArray || value instanceof AsObject);
		return complex;
	}

	public String toString() {
		String result = "";
		if (debug) {
			result = "9602000800";
		} else {
			// 96 0800 00 726573756C74 00
			result = Constants.ACTION_PUSH + "0800" + Constants.DATA_TYPE_STRING + VAR_RESULT + Constants.NULL_TERMINATOR;
		}
		
		if(!this.isComplex()) {
			// Not complex data, add the push code and length:
			AsByteLength byteLength = new AsByteLength(value.getByteSize());
			result += Constants.ACTION_PUSH + byteLength.toString();
		}
		
		result += value.toString();

		result += Constants.ACTION_SET_VARIABLE;

		// Allow domain? If so add allow domain statement to the SWF
		if(allowDomain) {
			result += getAllowDomainBytecode();
		}

		// Debug? If so, add the analyzer connector to the SWF
		if(debug) {
			LOG.info("Debug mode is on [version " + Debugger.VERSION + "]");
			result = Debugger.DEBUG_START + result + Debugger.DEBUG_END;
		}
		
		// 
		String doActionBlockSizeInBytes = StringUtils.getStringLengthInBytesHex(result, 4);
		result = Constants.ACTION_DO_ACTION + doActionBlockSizeInBytes + result;

		return result;
	}
	
	public String getAllowDomainBytecode() {
		if (StringUtils.isBlank(url)) {
			// No URL passed -- possibly called by legacy code, use the old _parent._url version.
			LOG.debug("No URL passed from client. Defaulting to old behavior. You must call System.security.allowDomain on the dataHolder for cross domain data loading to work.");
			return Constants.ALLOW_DOMAIN;
			
		} else {
			LOG.debug("Data SWF will allow access from " + url);
			// URL is passed, write that into the returned code
			String allowDomainBytecode = new AsString(url).toString(); 
			// The -13 is to accomodate the other elements being pushed to the 
			// stack in the hard-coded part of the bytecode.
			int allowDomainBytecodeLengthDec = allowDomainBytecode.length() / 2 + 13;
			
			String allowDomainBytecodeLength = StringUtils.getIntAsHex(allowDomainBytecodeLengthDec, 2);
			allowDomainBytecode = Constants.ACTION_PUSH + allowDomainBytecodeLength + allowDomainBytecode + Constants.SYSTEM_ALLOW_DOMAIN;
			return allowDomainBytecode;
		}
	}
}
